#include "cominicate.h"
//#include "spi_cc1101.h"
#include "CC1101/higerCC1101.h"
#include "USART.h"
#include "string.h"
#include "rcc.h"

baseToServerCmdDef baseToServerCmd;
baseToSlaveCmdDef baseToSlaveCmd;
slaveToBaseCmdDef slaveToBaseCmd;
serverToBaseCmdDef serverToBaseCmd;
rfMetricCmdDef tCmdMertric;

#ifdef CC_BASE
uint8_t deviCmdBuf[DEVICELEN];//服务器发给设备的命令， 基站缓存区域；

void cominicateDataInit(void)
{
    memset(deviCmdBuf, 0, sizeof(deviCmdBuf));

    baseToServerCmd.aucPreData[0] = 0x55;
    baseToServerCmd.aucPreData[1] = 0xFF;
    baseToServerCmd.ucDatalen = (sizeof(baseToServerCmdDef)-3);

    baseToSlaveCmd.ucDatalen = sizeof(baseToSlaveCmdDataDef);
    baseToSlaveCmd.tB2SlCmdData.usBaseAddr = ADDR_BASE;
}

/*******************修改说明****************************/
/*
 * 随笔
 * 改进功能介绍：
 * 1 标签洗手设备类型改为03；
 * 2 发送标号不增加；
 * 3 标签起来后查询，延时，标号不增加；
 * 4 基站对查询命令回复；
*/
/***********************************************/
void recvOkAndHandle(void)
{
    //上报给服务器
    if (slaveToBaseCmd.tSl2BCmdData.tAgreementType != SENDSEARCHNET) {

        baseToServerCmd.ucDatalen = sizeof(baseToServerCmdDef);

        baseToServerCmd.tAgreementType = BASETOSERVER;

        baseToServerCmd.usDevAddr = slaveToBaseCmd.tSl2BCmdData.usDevAddr;

        baseToServerCmd.usBaseAddr = slaveToBaseCmd.tSl2BCmdData.usBaseAddr;

        baseToServerCmd.tAction = slaveToBaseCmd.tSl2BCmdData.tAction;

        baseToServerCmd.ucBatVal = slaveToBaseCmd.tSl2BCmdData.ucBatVal;

        baseToServerCmd.eTagState = slaveToBaseCmd.tSl2BCmdData.ucTagState;

        baseToServerCmd.ucTransmitID = slaveToBaseCmd.tSl2BCmdData.ucTransmitID;
        {
            if (slaveToBaseCmd.tSl2BCmdData.tAgreementType == BOTTLTOBASE) {

                baseToServerCmd.tDeviceType = CCBOTTL;

            } else if (slaveToBaseCmd.tSl2BCmdData.tAgreementType == TAGTOBASE) {

                if (slaveToBaseCmd.tSl2BCmdData.tAction == TAGACTION_WASH_HANDS) {

                    baseToServerCmd.tDeviceType = 3;

                } else {

                    baseToServerCmd.tDeviceType = CCTAG;//wash tag send devicetype 3;

                }
            }
        }

        {
            uint8_t ucTempChek = 0;
            ucTempChek = getSumChekVal((uint8_t *)(&(baseToServerCmd.ucTransmitID)), (sizeof(baseToServerCmdDef) - 4));//last byte is check byte
            if (baseToServerCmd.usDevAddr <= DEVICELEN) {
                baseToServerCmd.ucSum = ucTempChek;
                {
                    uint8_t ucCount;
                    //                    debug("send to server:\r\n");
                    for (ucCount = 0; ucCount < sizeof(baseToServerCmdDef); ucCount++) {
                        //                        SendData(*(&baseToServerCmd.aucPreData[0]+ucCount));//发送至服务器
                        //                        printf("%02x", *(&baseToServerCmd.aucPreData[0]+ucCount));
                        printf("%02x", *(&baseToServerCmd.aucPreData[0]+ucCount));
                    }
#ifdef UPDATA_ADD_RSSI_LQI
                    //                    SendData(tCmdMertric.ucData[0]);//发送至服务器
                    //                    SendData(tCmdMertric.ucData[1]);
                    debug("ussi %d  %d dbm, LQI %d", tCmdMertric.ucData[0], tCmdMertric.cRssi, tCmdMertric.ucData[1]);
#endif
                }
            }
        }
        {
            memset(tCmdMertric.ucData, 0, sizeof(rfMetricCmdDef));
        }
    }


    {//回复从设备
        {
            if ( slaveToBaseCmd.tSl2BCmdData.tAgreementType == TAGTOBASE ) {
                baseToSlaveCmd.tB2SlCmdData.tAgreementType = BASETOTAG;
            } else if ( slaveToBaseCmd.tSl2BCmdData.tAgreementType == BOTTLTOBASE ) {
                baseToSlaveCmd.tB2SlCmdData.tAgreementType = BASETOBOTTL;
            } else if ( slaveToBaseCmd.tSl2BCmdData.tAgreementType == SENDSEARCHNET ) {
                baseToSlaveCmd.tB2SlCmdData.tAgreementType = BACKSEARCHNET;//回复寻网命令
            }
        }//back to slaver agreement;

        baseToSlaveCmd.tB2SlCmdData.usBaseAddr = ADDR_BASE;

        baseToSlaveCmd.tB2SlCmdData.usDevAddr = slaveToBaseCmd.tSl2BCmdData.usDevAddr;//查询输入
        {//标签上传“弯腰命令”时，基站将相应的位置清零；
            if (slaveToBaseCmd.tSl2BCmdData.usBaseAddr == ADDR_BASE) {//组网成功，知道基站地址
                if (slaveToBaseCmd.tSl2BCmdData.tAction == TAGACTION_BEND) {
                    deviCmdBuf[baseToSlaveCmd.tB2SlCmdData.usDevAddr] = TAGCMD_NOALARM;//弯腰动作时，基站将相应“命令缓存”位置清零
                }
                baseToSlaveCmd.tB2SlCmdData.ucCmd = deviCmdBuf[baseToSlaveCmd.tB2SlCmdData.usDevAddr];//查询结果
            } else {
                baseToSlaveCmd.tB2SlCmdData.ucCmd =TAGCMD_NOALARM;//寻网时候，基站回复的命令
            }
        }//back to slave cmd;

        while(MRFI_Transmit(&(baseToSlaveCmd.ucDatalen), MRFI_TX_TYPE_CCA));
    }
}

/**
\brief Called when a CoAP message is received for this resource.

\param[in] msg          The received message. CoAP header and options already
   parsed.
\param[in] coap_header  The CoAP header contained in the message.
\param[in] coap_options The CoAP options contained in the message.

\return
找到符合条件的位置个数（最多2），以及位置；
个数ret，位置用usRet[]保存；
*/
static uint8_t nno(uint16_t *usRet, uint16_t usFromPos, uint16_t usEndPos,
                   uint16_t usCicleLen, uint8_t ucPos)
{
    uint16_t i = 0;
    uint8_t ucTempVal = 0;
    //    debug("nno form %d to %d ", usFromPos, usEndPos);

    for ( i = usFromPos; i <= usEndPos; i++ ) {

        printf("%2x ", uartRecvBuf[i]);

        if ( ( uartRecvBuf[i] == 0x55 ) ) {

            //找出“55 ff” 位置，个数
            if ( ( i + 1 ) == CICLELEN ) {
                ucTempVal = uartRecvBuf[0];
            } else {
                ucTempVal = uartRecvBuf[i+1];
            }
            if(ucTempVal == 0xff) {
                usRet[ucPos] = i;
                ucPos++;

                if (ucPos == 2) {
                    //                     debug("");
                    return ucPos;
                }
            }
        }
    }
    //    debug("");
    return ucPos;//0或1
}

/**
\brief Called when a CoAP message is received for this resource.

\param[in] msg          The received message. CoAP header and options already
   parsed.
\param[in] coap_header  The CoAP header contained in the message.
\param[in] coap_options The CoAP options contained in the message.

\return Whether the response is prepared successfully.
//返回最先找到的字符串 位置 两个
//如果找到尾没找到 不处理 打印“record len enough but not found couple/signle 0xaa 0xff”
//find acouple return 1
//输入查询起点，终点；找出这些符合点的位置坐标；返回值代表符合位置条件的个数；最多为2
*/
static uint8_t search(uint16_t *retPos, uint16_t usFromPos, uint16_t usEndPos, uint16_t usCicleLen)
{
    uint16_t flag = 0;
    if (usFromPos > usEndPos) {
        flag += nno(retPos, usFromPos, (CICLELEN - 1), CICLELEN, flag);
        if (flag == 2) {
            return flag;
        } else {
            flag = nno(retPos, 0, usEndPos, CICLELEN, flag);
            return flag;
        }
    } else {
        flag = nno(retPos, usFromPos, usEndPos, CICLELEN, flag);
        return flag;
    }
}

static uint8_t writeInRecord(uint16_t usDevAdd, uint8_t cmd)
{
    if (usDevAdd >= DEVICELEN) {
        debug("writeInRecord usDevAdd error");
        return 0;
    } else {
        deviCmdBuf[usDevAdd] = cmd;
        return 1;
    }
}

void rccWriteBkpDr(uint32_t value);

void updataRecord(void)
{
    uint16_t usOldReadPos = 0;
    uint16_t usOldWritePos = 0;
    uint16_t retPos[2] = {0,0};
    uint16_t tempVal;
    uint16_t usTempLen_write;

    if (ucFlag_UART_FIFOOverFlow) {
        debug("uart write overflow!!");
        {
            usWritePos = 0;
            usReadPos = 0;
        }
    }
    uartDateLenUpdata();

    usOldReadPos = usReadPos;
    usOldWritePos = usWritePos;

    /***************************************************************
    * 循环中，串口缓存区“读地址”可变，“写地址”不变；
    ***************************************************************/
    //限定本次查询的范围
    usTempLen_write = usOldWritePos + ucWriteCicleNum*CICLELEN;
    //“缓存区数据长度”满足分析条件
    while ( ( usTempLen_write - usReadLen ) > CMDLENTHSERVETOBASE ) {
        //搜寻返回两个临近55 ff位置
        uint8_t ucTempRecord = search( retPos, usReadPos, usOldWritePos, CICLELEN );
        //        debug("ucTempRecord : %d ",ucTempRecord);
        if ( ucTempRecord == 2 ) {
            if (retPos[1] < retPos[0]) {
                tempVal = retPos[1] + (CICLELEN);
            } else {
                tempVal = retPos[1];
            }
            //            debug("tempVal %d retPos[0] %d retPos[1]%d",tempVal, retPos[0], retPos[1]);

            if ((tempVal - retPos[0]) == CMDLENTHSERVETOBASE) {
                debug("uart updata the data and posval[1] %d, posval[0] %d", retPos[1], retPos[0]);
                if ((retPos[0] + CMDLENTHSERVETOBASE) < CICLELEN) {

                    for (tempVal = retPos[0]; tempVal < (retPos[0] + CMDLENTHSERVETOBASE); tempVal++) {
                        printf("%02x", uartRecvBuf[tempVal]);
                    }

                    memcpy(&(serverToBaseCmd.aucPreData[0]), &(uartRecvBuf[retPos[0]]), CMDLENTHSERVETOBASE);
                    //                    debug("base from pre %x server src %x and cmd %x", serverToBaseCmd.aucPreData[0], serverToBaseCmd.usDevAddr, serverToBaseCmd.ucCmd);

                } else if ((retPos[0] + CMDLENTHSERVETOBASE) > CICLELEN) {

                    for (tempVal = retPos[0]; tempVal < CICLELEN; tempVal++) {
                        printf("%02x", uartRecvBuf[tempVal]);
                    }
                    memcpy(&(serverToBaseCmd.aucPreData[0]), &(uartRecvBuf[retPos[0]]), (CICLELEN - retPos[0]));

                    for (tempVal = 0; tempVal < retPos[1]; tempVal++) {
                        printf("%02x", uartRecvBuf[tempVal]);

                    }
                    memcpy((&(serverToBaseCmd.aucPreData[0]) + (CICLELEN - retPos[0])),
                            &(uartRecvBuf[0]), retPos[1]);
                    //                    debug("base from pre %x server src %x and cmd %x", serverToBaseCmd.aucPreData[0], serverToBaseCmd.usDevAddr, serverToBaseCmd.ucCmd);

                }
                //1求和校验
                //2地址校验
                if (serverToBaseCmd.tAgreementType == SERVERTOBASE) {
                    if (serverToBaseCmd.usBaseAddr == ADDR_BASE) {
                        if (serverToBaseCmd.ucCmd == 0xAA) {
                            rccWriteBkpDr(0x000000aa); //bkq write in
                            NVIC_SystemReset();//reset chip
                        } else if (serverToBaseCmd.ucCmd == 0x55) {
                            //                        debug("reset chip");
                            NVIC_SystemReset();//reset chip
                        } else if (serverToBaseCmd.tDeviceType == CCTAG) {
                            //3writeInRecord(usDevAdd, cmd);
                            writeInRecord(serverToBaseCmd.usDevAddr, serverToBaseCmd.ucCmd);
                        }
                    }
                }
            } else {
                //两个位置长度不对
                //                debug("two pos distance error");
            }
            usReadPos = retPos[1];
        } else if ( ucTempRecord == 1) {
            usReadPos = retPos[0];
        } else {
            usReadPos = usOldWritePos;
        }

        if (usOldReadPos > usReadPos) {
            ucReadCicleNum++;
            debug("read cicle ++");
            if (ucReadCicleNum == ucWriteCicleNum) {
                ucReadCicleNum = 0;
                ucWriteCicleNum = 0;
                usTempLen_write = usOldWritePos;//相应变化
                debug("clear the cicle num both");
            }
            usOldReadPos = usReadPos;
        }
        uartDataLenUpdata_read();
    }
}
#endif
uint8_t getSumChekVal(uint8_t *val, uint8_t len)
{
    uint8_t ucRet = 0;
    uint8_t ucCount = 0;

    for (ucCount = 0; ucCount < len; ucCount++) {
        ucRet += *(val + ucCount);
    }
    return ucRet;
}

uint32_t getTimeDifference(uint32_t recordtime, uint32_t realTime)
{
    if (recordtime > realTime) {
        return ((0xffffffff - recordtime) + realTime);
    }
    else {
        return (realTime - recordtime);
    }
}
